package com.quanyue.music.order.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaMsgService;
import cn.binarywang.wx.miniapp.bean.WxMaTemplateMessage;
import com.quanyue.auto.miniapp.support.MiniAppContext;
import com.quanyue.auto.util.AssertUtils;
import com.quanyue.auto.util.KeyGenerator;
import com.quanyue.auto.util.StringUtils;
import com.quanyue.music.domain.constant.NoPrefix;
import com.quanyue.music.domain.constant.PayResult;
import com.quanyue.music.domain.constant.RefundStatus;
import com.quanyue.music.domain.entity.*;
import com.quanyue.music.order.mapper.CodeMapper;
import com.quanyue.music.order.mapper.OrderMapper;
import com.quanyue.music.order.service.OrderService;
import com.quanyue.music.order.service.PayService;
import com.quanyue.music.order.type.OrderCreateRequest;
import com.quanyue.music.order.type.OrderResult;
import com.quanyue.music.system.mapper.IsTestMapper;
import com.quanyue.music.system.mapper.RechargeRuleMapper;
import com.quanyue.music.user.mapper.UserMapper;
import com.quanyue.music.user.mapper.VIPMapper;
import com.quanyue.music.user.service.UserService;
import jxl.Workbook;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import me.chanjar.weixin.common.exception.WxErrorException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static com.quanyue.music.domain.constant.TemplateId.PAY_SUCCESS;

@Service
public class OrderServiceImpl implements OrderService {
    private final String path = "/opt/music/admin/server/static/dist/excel/";
    @Autowired
    private CodeMapper codeMapper;
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private IsTestMapper isTestMapper;
    @Autowired
    private VIPMapper vipMapper;
    @Autowired
    private PayService payService;
    @Autowired
    private RechargeRuleMapper rechargeRuleMapper;
    @Autowired
    private UserService userService;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private WxMaMsgService wxMaMsgService;
    private Logger log = LoggerFactory.getLogger(this.getClass());

    @Override
    @Transactional
    public void afterPayComplete(String orderNo, String payId, PayResult result) {
        Order order = orderMapper.findByOrderNo(orderNo);
        log.info("订单号+支付ID: {}", orderNo + ">>>" + payId);
        FmVip fmVip = new FmVip();
        if (result == PayResult.SUCCESS) {
            RechargeRule rechargeRule = rechargeRuleMapper.findOneValid(order.getRechargeRule());
            log.info("vip充值时长: {}", rechargeRule.getRecharge());
            FmVip vip = vipMapper.findByUserIdValid(order.getUserId());
            if (orderMapper.findByPayId(payId) != null) return;
            log.info("debug order: ", order);
            order.setPayId(payId);
            orderMapper.updateSelective(order);
            // 检索过期记录
            String expiredUser = vipMapper.findExpiredUser(order.getUserId());
            if (StringUtils.isNotBlank(expiredUser))
                vipMapper.deleteOne(expiredUser);
            // 充值成功增加会员时长
            if (vip != null) {
                log.info("vip现在的时间: {}", vip.getEndTime());
                vip.setEndTime(vip.getEndTime().plusMonths(rechargeRule.getRecharge()));
                vipMapper.update(vip);
                log.info("vip更新的时间: {}", vip.getEndTime());
            } else {
                fmVip.setUserId(order.getUserId());
                fmVip.setRechargeRule(rechargeRule.getId());
                fmVip.setStartTime(LocalDateTime.now());
                fmVip.setEndTime(LocalDateTime.now().plusMonths(rechargeRule.getRecharge()));
                fmVip.setDelFlag(false);
                vipMapper.insert(fmVip);
            }
//            this.sendTemplate(order, fmVip, payId, rechargeRule, vip);
        }
//        else {
//            // 封装模板消息参数
//            List<WxMaTemplateMessage.Data> dataList = new ArrayList<>();
//            User user = userMapper.findOne(order.getUserId());
//            WxMaTemplateMessage message = WxMaTemplateMessage.newBuilder().build();
//            message.setToUser(user.getOpenId());
//            message.setTemplateId(PAY_FAIL.getTemplateId());
//            message.setPage(PAY_FAIL.getUrl());
//            message.setFormId(order.getPrepayId());
//            if (message != null) {
//                dataList.add(new WxMaTemplateMessage.Data("keyword1", LocalDateTime.now().toString()));
//                dataList.add(new WxMaTemplateMessage.Data("keyword2", "Wiggle FM会员"));
//                dataList.add(new WxMaTemplateMessage.Data("keyword3", "网络原因"));
//                dataList.add(new WxMaTemplateMessage.Data("keyword4", order.getOrderPrice().toString()));
//                dataList.add(new WxMaTemplateMessage.Data("keyword5", payId));
//                // TODO 客服电话
//                dataList.add(new WxMaTemplateMessage.Data("keyword6", ""));
//                try {
//                    message.setData(dataList);
//                    MiniAppContext.setMerchantNo(10100);
//                    wxMaMsgService.sendTemplateMsg(message);
//                } catch (WxErrorException e) {
//                    throw new RuntimeException(e);
//                } catch (NullPointerException e) {
//                    log.error("null: ", e);
//                }
//            }
//        }
    }

    private void sendTemplate(Order order, FmVip fmVip, String payId, RechargeRule rechargeRule, FmVip vip) {
        // 封装模板消息参数
        List <WxMaTemplateMessage.Data> dataList = new ArrayList <>();
        User user = userMapper.findOne(order.getUserId());
        WxMaTemplateMessage message = WxMaTemplateMessage.newBuilder().build();
        message.setToUser(user.getOpenId());
        message.setTemplateId(PAY_SUCCESS.getTemplateId());
        message.setPage(PAY_SUCCESS.getUrl());
        message.setFormId(order.getPrepayId());
        if (message != null) {
            String content = "欢迎成功入伙歪果！快来关注歪果公众号，一起变成更有趣的人吧";
            dataList.add(new WxMaTemplateMessage.Data("keyword1", order.getOrderPrice().toString()));
            dataList.add(new WxMaTemplateMessage.Data("keyword2", rechargeRule.getRecharge().toString()));
            dataList.add(new WxMaTemplateMessage.Data("keyword3", vip == null ? fmVip.getEndTime().toString() : vip.getEndTime().toString()));
            dataList.add(new WxMaTemplateMessage.Data("keyword4", user.getNickName()));
            dataList.add(new WxMaTemplateMessage.Data("keyword5", payId));
            dataList.add(new WxMaTemplateMessage.Data("keyword6", content));
            try {
                message.setData(dataList);
                MiniAppContext.setMerchantNo(10100);
                log.info("debug message:", message);
                wxMaMsgService.sendTemplateMsg(message);
            } catch (WxErrorException e) {
                log.error("weixin error: ", e);
                Integer str = e.getError().getErrorCode();
                try {
                    Thread.sleep(1000);
                    this.sendTemplate(order, fmVip, payId, rechargeRule, vip);
                } catch (Exception ie) {
                    log.error("", ie);
                }
            } catch (NullPointerException e) {
                log.error("null: ", e);
            }
        }
    }

    @Override
    public void afterRefundComplete(String orderNo, RefundStatus refundStatus) {

    }

    @Override
    @Transactional
    public OrderResult createOrder(OrderCreateRequest create, User user, String userIp) {
        RechargeRule rechargeRule = rechargeRuleMapper.findOneValid(create.getRuleId());
        AssertUtils.notNull(rechargeRule, "没有该充值类型");
        Order order = new Order();
        order.setUserId(user.getId());
        order.setRechargeRule(rechargeRule.getId());
        order.setOrderPrice(rechargeRule.getPrice());
        order.setOrderNo(KeyGenerator.createOrderNo(NoPrefix.ORDER.value(), 10100, user.getId()));
        order.setPayId("NONE");
        order.setPayChannel(create.getPayChannel());
        order.setCreateTime(LocalDateTime.now());
        order.setDelFlag(false);
        orderMapper.insert(order);

        Map <String, Object> payInfo = payService.pay(10100, order.getOrderPrice(), order.getOrderNo(), user, userIp);
        String prepayId = ((String) payInfo.get("package")).substring(10);
        order.setPrepayId(prepayId);
        orderMapper.updateSelective(order);
        OrderResult result = new OrderResult();
        result.setOrder(order);
        result.setPayInfo(payInfo);
        return result;
    }


    @Override
    @Transactional
    public Boolean convert(String code, String userId, String userIp) {
        InvitationCode check = codeMapper.findValid(code);
        AssertUtils.notNull(check, "没有该邀请码");
        IsTest isTest = isTestMapper.findAll().get(0);
        // 权限邀请码验证(分为普通用户和内部员工邀请码验证)
        if (check.getInsideUser()) {
            codeMapper.updateUser(userId);
        } else if (isTest.getIstest()) {
            throw new AssertUtils.ValidateException("您没有权限!");
        }
        // 检索过期记录
        String expiredUser = vipMapper.findExpiredUser(userId);
        if (StringUtils.isNotBlank(expiredUser))
            vipMapper.deleteOne(expiredUser);
        // 会员兑换邀请码
        FmVip vip = vipMapper.findByUserIdValid(userId);
        if (vip != null) {
            vip.setEndTime(vip.getEndTime().plusMonths(codeMapper.findValid(code).getTime()));
            vipMapper.update(vip);
        } else {
            FmVip fmVip = new FmVip();
            fmVip.setUserId(userId);
            fmVip.setRechargeRule(code);
            fmVip.setStartTime(LocalDateTime.now());
            fmVip.setEndTime(LocalDateTime.now().plusMonths(codeMapper.findValid(code).getTime()));
            fmVip.setDelFlag(false);
            vipMapper.insert(fmVip);
        }
        this.codeDelete(code);
        User user = userMapper.findOne(userId);
        if (user.getInsideUser()) {
            return true;
        }
        return userService.getAddressByIP(userIp);
    }

    @Override
    public List <InvitationCode> createCode(Integer month, Integer number, String isIp, String remake) {
        LocalDateTime dateTime = LocalDateTime.now();
        List <InvitationCode> codeList = new ArrayList <>();
        for (int i = 0; i < number; i++) {
            InvitationCode code = new InvitationCode();
            code.setCode(KeyGenerator.shortUuid());
            code.setCreateTime(dateTime);
            code.setDelFlag(false);
            code.setTime(month);
            code.setInsideUser(isIp.equals("false"));
            code.setRemark(remake);
            codeMapper.insert(code);
            codeList.add(code);
        }
        return codeList;
    }

    @Override
    public List <InvitationCode> codeList() {
        return codeMapper.findTotalValid();
    }

    @Override
    public void codeDelete(String code) {
        InvitationCode codeAction = new InvitationCode();
        codeAction.setCode(code);
        codeAction.setDelFlag(true);
        codeMapper.updateSelective(codeAction);
    }

    @Override
    public Order findOrderByNo(String orderNo) {
        return orderMapper.findByOrderNo(orderNo);
    }

    @Override
    public String codeExcel() {
        return this.createExcel(codeList());
    }


    private String createExcel(List <InvitationCode> codes) {
        try {
            String fileName = "InviteCode.xls";
            File file = new File(path);
            if (!file.exists()) {
                file.mkdirs();
            }
            //  打开文件
            WritableWorkbook book = Workbook.createWorkbook(new File(path, fileName));
            //  生成名为“第一页”的工作表，参数0表示这是第一页
            WritableSheet sheet = book.createSheet(" 第一页 ", 0);

            //  将定义好的单元格添加到工作表中  在Label对象的构造子中指名单元格位置是第一列第一行(0,0)
            sheet.addCell(new Label(0, 0, "邀请码"));
            sheet.addCell(new Label(1, 0, "时限"));
            sheet.addCell(new Label(2, 0, "内部员工"));
            sheet.addCell(new Label(3, 0, "创建时间"));
            sheet.addCell(new Label(4, 0, "备注"));
            int row = 1;
            String remark = "";
            for (InvitationCode code : codes) {
                int column = 0;
                if (StringUtils.isNotBlank(code.getRemark()))
                    remark = code.getRemark();
                sheet.addCell(new Label(column++, row, code.getCode()));
                sheet.addCell(new Label(column++, row, code.getTime().toString() + "个月"));
                sheet.addCell(new Label(column++, row, code.getInsideUser().toString()));
                sheet.addCell(new Label(column++, row, code.getCreateTime().toString()));
                sheet.addCell(new Label(column++, row, remark));
                ++row;
            }
            //  写入数据并关闭文件
            book.write();
            book.close();
            return "/excel/" + fileName;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
